package com.zhiqian.service.impl;

import com.zhiqian.enums.RpcError;
import com.zhiqian.exception.RpcException;
import com.zhiqian.service.ServiceRegistry;
import lombok.extern.slf4j.Slf4j;
import org.apache.zookeeper.*;
import org.apache.zookeeper.data.Stat;

import java.net.InetSocketAddress;

//服务注册与发现。以Zookeeper的方式实现
@Slf4j
public class ZookeeperServiceRegistry implements ServiceRegistry {
    //连接的Zookeeper客户端
    private  final String connectString;
    //与Zookeeper服务器进行交互的实例
    private  ZooKeeper zooKeeper;
    //连接超时时间
    private final int sessionTimeout=50000;

    private final String location="/provider";

    public ZookeeperServiceRegistry(String hostName){
        this.connectString=hostName+":"+2181;
        try {
            zooKeeper=new ZooKeeper(connectString, sessionTimeout, new Watcher() {
                @Override
                public void process(WatchedEvent watchedEvent) {
                }
            });
            Stat stat = zooKeeper.exists(location, false);
            if(stat==null){
                zooKeeper.create(location,"ServerNode".getBytes(),ZooDefs.Ids.OPEN_ACL_UNSAFE,CreateMode.PERSISTENT);
            }
        } catch (Exception e) {
            log.error("初始化连接Zookeeper出现错误：{}",e);
            throw new RpcException(RpcError.FAILED_TO_CONNECT_TO_SERVICE_REGISTRY.getMessage());
        }
    }

    @Override
    public void registry(String serviceName, InetSocketAddress inetSocketAddress) {
        String hostName = inetSocketAddress.getHostString();
        int port = inetSocketAddress.getPort();
        String address=hostName+":"+port;
        try {
            String nodeName = zooKeeper.create(location +"/"+serviceName, address.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
            log.info("服务已上线：{}，暴露地址为：{}",serviceName,address);
        }catch (InterruptedException |KeeperException e) {
            log.error("注册服务时有错误发生：{}",e);
            throw new RpcException(RpcError.REGISTER_SERVICE_FAILED.getMessage());
        }


    }

    @Override
    public InetSocketAddress lookupService(String serviceName) {
        try {
            Stat stat = zooKeeper.exists(location + "/" + serviceName, false);
            if (stat==null){
                log.error("生产者未注册该服务，获取请求地址失败");
                throw new RpcException(RpcError.SERVICE_NOT_REGISTERED.getMessage());
            }
            byte[] bytes = zooKeeper.getData(location + "/"+serviceName, false, null);
            String string = new String(bytes);
            String[] split = string.split(":");
            return new InetSocketAddress(split[0], Integer.valueOf(split[1]));
        } catch (InterruptedException |KeeperException e) {
            log.error("获取服务有错误发生：{}",e);
            throw new RpcException(RpcError.GET_SERVICE_FAILED.getMessage());
        }
    }
}
